﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Win32;
using Microsoft.Xna.Framework.Graphics;
using Phoenix.Xna.Framework;
using Phoenix.Xna.Framework.ContentPipeline;
using Phoenix.Xna.Framework.Presentation;
using XnaGraphics = Microsoft.Xna.Framework.Graphics;
using EffectMapStudio.Properties;
using Phoenix.Xna.Framework.Graphics;
using Phoenix.Xna.Framework.Serialization;
using EffectMapStudio.Editors;
using System.Xml.Linq;

namespace EffectMapStudio
{
    using Microsoft.Xna.Framework;

    public partial class Window1 : Window
    {
        private GameWrapper _game = new GameWrapper();
        private string _contentPath = string.Format("{0}\\{1}", EffectMapStudio.Properties.Settings.Default.RootPath, EffectMapStudio.Properties.Settings.Default.ContentRoot);

        public static readonly DependencyProperty EffectsProperty = DependencyProperty.Register("Effects", typeof(EffectWrapperCollection), typeof(Window1));

        public EffectWrapperCollection Effects
        {
            get { return (EffectWrapperCollection)GetValue(EffectsProperty); }
            set { SetValue(EffectsProperty, value); }
        }

        public Window1()
        {
            InitializeComponent();
            Effects = new EffectWrapperCollection();
        }

        private void OnOpenClick(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(EffectMapStudio.Properties.Settings.Default.RootPath))
            {
                MessageBox.Show("You must set the absolute content path.", "Content Path Error", MessageBoxButton.OK, MessageBoxImage.Warning);
            }
            else
            {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.InitialDirectory = _contentPath;
                ofd.RestoreDirectory = true;
                ofd.Filter = "Effect Files (.fx)|*.fx";

                if (ofd.ShowDialog() == true)
                {
                    CompilerOptions options = CompilerOptions.None | CompilerOptions.SkipOptimization;
                    CompiledEffect ce = XnaGraphics.Effect.CompileEffectFromFile(ofd.OpenFile(), null, null, options, TargetPlatform.Windows);

                    if (ce.Success)
                    {
                        Effects.Add(new EffectWrapper(System.IO.Path.GetFileNameWithoutExtension(ofd.FileName), 
                            ResolvePath(System.IO.Path.GetDirectoryName(ofd.FileName), System.IO.Path.GetFileNameWithoutExtension(ofd.FileName)), 
                            new Effect(_game.GraphicsDevice, ce.GetEffectCode(), options, null)));
                    }
                }
            }
        }

        private string ResolvePath(string absolutePath, string file)
        {
            string resourcePath = (absolutePath.Contains(_contentPath)) ? absolutePath : _contentPath;
            resourcePath = string.Format("{0}\\{1}", resourcePath, file);
            return resourcePath.Substring(_contentPath.Length);
        }

        private void OnSettingsClick(object sender, RoutedEventArgs e)
        {
            Settings dlg = new Settings();
            dlg.ShowDialog();
        }

        private void OnEditClick(object sender, RoutedEventArgs e)
        {
            EffectParameterWrapper parameter = (EffectParameterWrapper)((ListViewItem)((Button)sender).Tag).Content;

            if (parameter.IsType<Matrix>())
            {
                MatrixEditor dlg = new MatrixEditor();
                dlg.ShowDialog();
            }
            else if (parameter.IsType<Texture>() || parameter.IsType<Texture2D>())
            {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.InitialDirectory = _contentPath;
                ofd.RestoreDirectory = true;
                ofd.Filter = "Bitmap Files (.bmp)|*.bmp|JPEG Files (.jpg)|*.jpg|PNG Files (.png)|*.png";

                if (ofd.ShowDialog() == true)
                {
                    parameter.Value = ResolvePath(System.IO.Path.GetDirectoryName(ofd.FileName), System.IO.Path.GetFileNameWithoutExtension(ofd.FileName));
                }
            }
        }

        private void OnSaveClick(object sender, RoutedEventArgs e)
        {
            EffectWrapper ew = Effects[_effectList.SelectedIndex];
            EffectMap map = ew.GenerateEffectMap();
            Serializer s = new Serializer();
            XElement element = s.SerializeAsXElement(map);
            element.Save("EffectMap.effectmap");
        }

        private static T FindAncestor<T>(DependencyObject current)
            where T : DependencyObject
        {
            do
            {
                if (current is T)
                {
                    return (T)current;
                }
                current = VisualTreeHelper.GetParent(current);
            }
            while (current != null);

            return null;
        }

        private object GetObjectDataFromPoint(ListBox source, System.Windows.Point point)
        {
            // get the element under the mouse
            UIElement element = source.InputHitTest(point) as UIElement;

            if (element != null)
            {
                object data = DependencyProperty.UnsetValue;

                while (data == DependencyProperty.UnsetValue)
                {
                    data = source.ItemContainerGenerator.ItemFromContainer(element);

                    if (data == DependencyProperty.UnsetValue)
                    {
                        element = VisualTreeHelper.GetParent(element) as UIElement;
                    }

                    if (element == source)
                    {
                        return null;
                    }
                }

                if (data != DependencyProperty.UnsetValue)
                {
                    return data;
                }
            }

            return null;
        }

        private void ListBox_ContextMenuOpening(object sender, ContextMenuEventArgs e)
        {
            string id = (_effectList.SelectedItem as EffectWrapper).ID;

            foreach (EffectWrapper ew in Effects)
            {
                if (string.Compare(ew.ID, id) != 0)
                {
                    _subEffectsContextMenu.Items.Add(new MenuItem() { Header = ew.ID });
                }
            }
        }
    }
}
